import httpx
import json
import time
import logging
import uuid
import asyncio
from typing import Dict, Any, AsyncGenerator

from fastapi import HTTPException
from fastapi.responses import StreamingResponse, JSONResponse

from app.core.config import settings
from app.providers.base_provider import BaseProvider
from app.utils.sse_utils import create_sse_data, create_chat_completion_chunk, DONE_CHUNK

logger = logging.getLogger(__name__)

class ArticleSummarizerProvider(BaseProvider):
    def __init__(self):
        self.client = httpx.AsyncClient(timeout=settings.API_REQUEST_TIMEOUT)
        self.api_url = "https://pjfuothbq9.execute-api.us-east-1.amazonaws.com/upload-link"

    async def chat_completion(self, request_data: Dict[str, Any]) -> StreamingResponse:
        
        async def stream_generator() -> AsyncGenerator[bytes, None]:
            request_id = f"chatcmpl-{uuid.uuid4()}"
            try:
                article_link = self._extract_link(request_data)
                payload = self._prepare_payload(article_link)
                headers = self._prepare_headers()

                response = await self.client.post(self.api_url, headers=headers, json=payload)
                response.raise_for_status()

                # 战术-双重JSON解析 (Tactic-DoubleJSONParse)
                outer_data = response.json()
                body_str = outer_data.get("result", {}).get("body")
                if not body_str or not isinstance(body_str, str):
                    raise ValueError("上游响应格式不正确：'result.body' 字段缺失或非字符串。")
                
                inner_data = json.loads(body_str)
                summary_text = inner_data.get("summary")
                if not summary_text:
                    raise ValueError("解析后的摘要内容为空。")

                # 战术-伪流式生成 (Tactic-PseudoStream)
                # 逐字发送以模拟打字机效果
                for char in summary_text:
                    chunk = create_chat_completion_chunk(request_id, settings.DEFAULT_MODEL, char)
                    yield create_sse_data(chunk)
                    await asyncio.sleep(0.01) # 控制流速
                
                final_chunk = create_chat_completion_chunk(request_id, settings.DEFAULT_MODEL, "", "stop")
                yield create_sse_data(final_chunk)
                yield DONE_CHUNK

            except Exception as e:
                logger.error(f"处理流时发生错误: {e}", exc_info=True)
                error_message = f"内部错误: {str(e)}"
                error_chunk = create_chat_completion_chunk(request_id, settings.DEFAULT_MODEL, error_message, "stop")
                yield create_sse_data(error_chunk)
                yield DONE_CHUNK

        return StreamingResponse(stream_generator(), media_type="text/event-stream")

    def _extract_link(self, request_data: Dict[str, Any]) -> str:
        messages = request_data.get("messages", [])
        if not messages or not isinstance(messages, list):
            raise HTTPException(status_code=400, detail="请求体中缺少 'messages' 字段。")
        
        last_message = messages[-1]
        if last_message.get("role") != "user" or not last_message.get("content"):
            raise HTTPException(status_code=400, detail="最后一条消息必须是 user 角色且包含内容。")
        
        link = last_message["content"]
        if not link.startswith("http"):
             raise HTTPException(status_code=400, detail="内容必须是一个有效的 URL 链接。")
        return link

    def _prepare_headers(self) -> Dict[str, str]:
        return {
            "accept": "*/*",
            "accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
            "content-type": "application/json",
            "origin": "https://articlesummarizer.com",
            "referer": "https://articlesummarizer.com/",
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
        }

    def _prepare_payload(self, link: str) -> Dict[str, Any]:
        return {
            "link": link,
            "website": "article-summarizer"
        }

    async def get_models(self) -> JSONResponse:
        model_data = {
            "object": "list",
            "data": [
                {"id": name, "object": "model", "created": int(time.time()), "owned_by": "lzA6"}
                for name in settings.KNOWN_MODELS
            ]
        }
        return JSONResponse(content=model_data)
